/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.httpserver;
import java.util.Enumeration;
import java.io.*;
import java.net.URL;
import java.net.MalformedURLException;
import java.net.InetAddress;
import java.lang.reflect.InvocationTargetException;
import org.openide.modules.ModuleInstall;
import org.openide.execution.Executor;
import org.openide.execution.NbClassPath;
import org.openide.util.NbBundle;
import org.openide.TopManager;
import org.openide.NotifyDescriptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.web.core.Container;
import com.sun.web.core.Context;
import com.sun.web.core.HttpServletRequestFacade;
import com.sun.web.core.SecurityModule;
import com.sun.web.server.EndpointManager;
import com.sun.web.server.HttpServer;
import com.sun.web.server.HttpServerException;
/**
* Module installation class for Http Server
*
* @author Petr Jiricka
*/
public class HttpServerModule extends ModuleInstall implements Externalizable {
private static HttpServer server;
private static Thread serverThread;
private static boolean inSetRunning = false;
static final long serialVersionUID =8562026516563511530L;
/** Module installed again.
* Add applet executor
*/
public void restored() {
try {
org.openide.util.HttpServer.registerServer(HttpServerSettings.OPTIONS);
}
catch (SecurityException e) {}
}
/** Module is being closed. */
public boolean closing () {
// stop the server, don't set the running status
try {
org.openide.util.HttpServer.deregisterServer(HttpServerSettings.OPTIONS);
}
catch (SecurityException e) {
// pending - why do I get SecurityException ?
}
synchronized (HttpServerSettings.OPTIONS) {
stopHTTPServer();
}
return true; // agree to close
}
/** initiates HTTPServer so it runs */
static void initHTTPServer() {
if (inSetRunning)
return;
synchronized (HttpServerSettings.OPTIONS) {
if (inSetRunning)
return;
inSetRunning = true;
try {
if ((serverThread != null) && (!HttpServerSettings.OPTIONS.running)) {
// another thread is trying to start the server, wait for a while and then stop it if it's still bad
try {
Thread.currentThread().sleep(2000);
}
catch (InterruptedException e) {}
if ((serverThread != null) && (!HttpServerSettings.OPTIONS.running)) {
serverThread.stop();
serverThread = null;
}
}
if (serverThread == null) {
serverThread = new Thread("HTTPServer") { // NOI18N
public void run() {
try {
server = buildServer();
server.start();
HttpServerSettings.OPTIONS.runSuccess();
// this is not a debug message, this is a server startup message
if (HttpServerSettings.OPTIONS.isStartStopMessages())
System.out.println(java.text.MessageFormat.format(NbBundle.getBundle(HttpServerModule.class).
getString("CTL_ServerStarted"), new Object[] {new Integer(HttpServerSettings.OPTIONS.getPort())}));
}
catch (ThreadDeath td) {
throw td;
}
catch (Throwable ex) {
// couldn't start
serverThread = null;
inSetRunning = false;
HttpServerSettings.OPTIONS.runFailure();
}
finally {
HttpServerSettings.OPTIONS.setStartStopMessages(true);
}
}
};
serverThread.start();
}
// wait for the other thread to start the server
try {
HttpServerSettings.OPTIONS.wait(HttpServerSettings.SERVER_STARTUP_TIMEOUT);
}
catch (Exception e) {
}
}
finally {
inSetRunning = false;
}
}
}
/** stops the HTTP server */
static void stopHTTPServer() {
if (inSetRunning)
return;
synchronized (HttpServerSettings.OPTIONS) {
if (inSetRunning)
return;
inSetRunning = true;
try {
if ((serverThread != null) && (server != null)) {
try {
server.stop();
serverThread.join();
}
catch (InterruptedException e) {
serverThread.stop();
/* deprecated, but this really is the last resort,
only if everything else failed */
}
catch (HttpServerException e) {
//e.printStackTrace();
serverThread.stop();
/* deprecated, but this really is the last resort,
only if everything else failed */
}
serverThread = null;
// this is not a debug message, this is a server shutdown message
if (HttpServerSettings.OPTIONS.isStartStopMessages())
System.out.println(NbBundle.getBundle(HttpServerModule.class).
getString("CTL_ServerStopped"));
}
}
finally {
inSetRunning = false;
}
}
}
private static HttpServer buildServer() {
HttpServerSettings op = HttpServerSettings.OPTIONS;
HttpServer server = new NbHttpServer(op.getPort(), null, null);
try {
server.setDocumentBase(new URL("file:///nonexistingdirectory")); // NOI18N
}
catch (MalformedURLException e) {
throw new InternalError();
}
Context context = server.getDefaultContext();
context.setSecurityModule (new NbSecurityModule (context));
context.setClassLoader(TopManager.getDefault().systemClassLoader());
Container container = context.getContainer();
container.addServlet("repositoryHandler", "org.netbeans.modules.httpserver.RepositoryServlet"); // NOI18N
container.addMapping("repositoryHandler", op.getRepositoryBaseURL()); // NOI18N
container.addServlet("classpathHandler", "org.netbeans.modules.httpserver.ClasspathServlet"); // NOI18N
container.addMapping("classpathHandler", op.getClasspathBaseURL()); // NOI18N
return server;
}
static class NbHttpServer extends HttpServer {
public NbHttpServer(int i, InetAddress inetaddress, String s) {
super(i, inetaddress, s);
}
public void start() throws HttpServerException {
File wd = NbClassPath.toFile(
TopManager.getDefault().getRepository().getDefaultFileSystem().getRoot());
wd = new File(wd, "httpwork"); // NOI18N
try {
java.lang.reflect.Field ff = HttpServer.class.getDeclaredField("isWorkDirPersistent"); // NOI18N
ff.setAccessible(true);
boolean bb = ff.getBoolean(this);
getDefaultContext().setWorkDir(wd, bb /*isWorkDirPersistent*/);
getDefaultContext().init();
EndpointManager endpointmanager = EndpointManager.getManager();
// endpointmanager.startServer(this);
java.lang.reflect.Method mm = EndpointManager.class.getDeclaredMethod("startServer", new Class[] {HttpServer.class}); // NOI18N
mm.setAccessible(true);
mm.invoke(endpointmanager, new Object[] { this });
}
catch (NoSuchMethodException e) {
if (Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N
e.printStackTrace();
throw new IllegalArgumentException();
}
catch (NoSuchFieldException e) {
if (Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N
e.printStackTrace();
throw new IllegalArgumentException();
}
catch (IllegalAccessException e) {
if (Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N
e.printStackTrace();
throw new IllegalArgumentException();
}
catch (InvocationTargetException e) {
Throwable th = e.getTargetException();
throw ((HttpServerException)th);
}
}
}
static class NbSecurityModule implements SecurityModule {
public NbSecurityModule (Context context1) {
context = context1;
}
public Context getContext() {
return context;
}
public boolean authenticateRequest(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
throws IOException {
return true;
}
public boolean authorizeRequest(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse)
throws IOException {
HttpServerSettings op = HttpServerSettings.OPTIONS;
String requestURI = httpservletrequest.getRequestURI ();
String contextPath = context.getPath();
String lookupPath = requestURI.substring(contextPath.length(), requestURI.length());
int i = lookupPath.indexOf("?"); // NOI18N
if(i > -1) lookupPath = lookupPath.substring(0, i);
if(lookupPath.length() < 1) lookupPath = "/"; // NOI18N
String s = lookupPath.toLowerCase();
/*System.out.println("s :" + s);
System.out.println("rep :" + op.getRepositoryBaseURL());*/ // NOI18N
if(s.startsWith("/servlet/")) { // NOI18N
//System.out.println("security check OK 1"); // NOI18N
return true;
}
if(s.startsWith("/web-inf")) { // NOI18N
httpservletresponse.sendError(403);
return false;
} if (s.startsWith(op.getRepositoryBaseURL() + "/") || s.startsWith(op.getClasspathBaseURL() + "/")) { // NOI18N
//System.out.println("security check OK 2"); // NOI18N
return true;
} else {
httpservletresponse.sendError(404);
return false;
}
}
private Context context;
}
}
/*
* Log
* 38 Gandalf 1.37 1/13/00 Petr Jiricka More i18n
* 37 Gandalf 1.36 1/12/00 Petr Jiricka i18n
* 36 Gandalf 1.35 1/11/00 Petr Jiricka Cleanup
* 35 Gandalf 1.34 1/9/00 Petr Jiricka Cleanup
* 34 Gandalf 1.33 12/1/99 Ales Novak bugfix - working
* directory is not system - system is deleted no more
* 33 Gandalf 1.32 11/27/99 Patrik Knakal
* 32 Gandalf 1.31 11/25/99 Petr Jiricka - Another
* security-related fix - for URLs starting with an allowed substring but
* continuing further on. - Relaxed security to allow executing arbitrary
* servlets - Fixed undesirable creation of "work" directory
* 31 Gandalf 1.30 11/24/99 Ian Formanek Fixed bug 4767 -
* Security problem: Internal HTTP Server allows access to directories
* including and below root directory under NT. Could default Project
* Settings | HTTP Server | Grant Access To to 127.0.0.0?
* 30 Gandalf 1.29 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 29 Gandalf 1.28 10/10/99 Petr Hamernik console debug messages
* removed.
* 28 Gandalf 1.27 10/7/99 Petr Jiricka
* 27 Gandalf 1.26 10/6/99 Petr Jiricka Removed module
* (de)serialization
* 26 Gandalf 1.25 10/6/99 Petr Jiricka Removed debug DumpStack
* 25 Gandalf 1.24 10/5/99 Petr Jiricka
* 24 Gandalf 1.23 10/1/99 Petr Hrebejk org.openide.modules.ModuleInstall
* changed to class + some methods added
* 23 Gandalf 1.22 9/30/99 Petr Jiricka Jetty -> JSWDK (TomCat)
* 22 Gandalf 1.21 9/8/99 Petr Jiricka SecurityException fix
* 21 Gandalf 1.20 9/8/99 Petr Jiricka Fixed
* NullPointerException at startup
* 20 Gandalf 1.19 8/17/99 Petr Jiricka Externalization - server
* startup during the first IDE start
* 19 Gandalf 1.18 8/9/99 Petr Jiricka Fixed bug with multiple
* restarts of the server on IDE startup
* 18 Gandalf 1.17 7/24/99 Petr Jiricka
* 17 Gandalf 1.16 7/3/99 Petr Jiricka
* 16 Gandalf 1.15 7/3/99 Petr Jiricka
* 15 Gandalf 1.14 6/23/99 Petr Jiricka
* 14 Gandalf 1.13 6/22/99 Petr Jiricka
* 13 Gandalf 1.12 6/11/99 Jaroslav Tulach System.out commented
* 12 Gandalf 1.11 6/9/99 Ian Formanek ---- Package Change To
* org.openide ----
* 11 Gandalf 1.10 6/8/99 Petr Jiricka
* 10 Gandalf 1.9 6/1/99 Petr Jiricka
* 9 Gandalf 1.8 6/1/99 Petr Jiricka
* 8 Gandalf 1.7 5/31/99 Petr Jiricka
* 7 Gandalf 1.6 5/28/99 Petr Jiricka
* 6 Gandalf 1.5 5/25/99 Petr Jiricka
* 5 Gandalf 1.4 5/17/99 Petr Jiricka
* 4 Gandalf 1.3 5/17/99 Petr Jiricka
* 3 Gandalf 1.2 5/11/99 Petr Jiricka
* 2 Gandalf 1.1 5/10/99 Petr Jiricka
* 1 Gandalf 1.0 5/7/99 Petr Jiricka
* $
*/